package ua.kharkov.khpi.tarasenko.bach.analysis.prefixspan;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;


public class RulesGenerator {

	private Node rootNode;
	private int minLength;
	private int maxLength;
	private int recomNumber;

	public RulesGenerator(Node rootNode, int minLength, int maxLength,
			int recomNumber) {
		this.rootNode = rootNode;
		this.minLength = minLength;
		this.maxLength = maxLength;
		this.recomNumber = recomNumber;
	}

	public Set<Item> getRecommendation(Sequence currentAccessSeq) {

		TreeSet<Item> recs = new TreeSet<Item>();

		int seqSize = currentAccessSeq.size();

		Sequence currSeqAprSize = new Sequence();

		if (seqSize > maxLength) {
			currSeqAprSize.addSequence(currentAccessSeq.subsequence(seqSize
					- maxLength));
		} else {
			currSeqAprSize = currentAccessSeq;
		}

		Node currNode = new Node();

		OUTER: while (seqSize > minLength) {
			System.out.println("new it" + currSeqAprSize.getItems());
			currNode = rootNode;
			List<Item> items = currSeqAprSize.getItems();
			Iterator<Item> it = items.iterator();
			while (it.hasNext()) {
				Item item = it.next();
				if (containsItem(currNode, item)) {
					currNode = currNode.getChildNode(item.getItem());
				} else {
					currSeqAprSize = removeFirstElement(currSeqAprSize);
					seqSize = currSeqAprSize.size();
					if (seqSize == 0) {
						break OUTER;
					}
					continue OUTER;
				}
			}

			if ((!(currNode.getChildrenNodes().size() >= 3))
					&& (currSeqAprSize.size() > 1)) {
				currSeqAprSize = removeFirstElement(currSeqAprSize);
				continue OUTER;
			}

			break;
		}

		if (currNode.hasChildren() && currNode != rootNode) {
			List<Node> children = currNode.getChildrenNodes();
			for (Node node : children) {
				recs.add(node.getItem());
				System.out.println(node.getItem());
			}
		}
		Set<Item> result = new HashSet<Item>();
		int count = 0;
		for (Item item : recs) {
			if (count == recomNumber) {
				break;
			}
			result.add(item);
		}
		return result;
	}

	private Sequence removeFirstElement(Sequence old) {
		Sequence newSeq = new Sequence();
		newSeq.addSequence(old.subsequence(1));
		return newSeq;
	}

	private boolean containsItem(Node nodeToCheck, Item item) {
		boolean result = false;
		for (Node node : nodeToCheck.getChildrenNodes()) {
			if (node.getItem().equals(item)) {
				result = true;
				break;
			}
		}
		return result;
	}
}
